home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / newmat03.lha / newmat03 / newmat.txt < prev    next >
Text File  |  1993-08-08  |  53KB  |  1,500 lines

  1. //$$ newmat.txt            Documentation file
  2.  
  3.  
  4.    Documentation for newmat03, an experimental matrix package in C++.
  5.    ==================================================================
  6.  
  7.  
  8. MATRIX PACKAGE                                           25 November, 1991
  9.  
  10. Copyright (C) 1991: R B Davies and DSIR
  11.  
  12. Permission is granted to use but not to sell.
  13.  
  14.  
  15. Contents
  16. ========
  17.  
  18. General description
  19. Is this the package you need?
  20. Changes
  21. Where you can get a copy of this package
  22. Compiler performance
  23. Example
  24. Detailed documentation
  25.    Customising
  26.    Constructors
  27.    Elements of matrices
  28.    Matrix copy
  29.    Unary operators
  30.    Binary operators
  31.    Combination of a matrix and scalar
  32.    Scalar functions of matrices
  33.    Submatrix operations
  34.    Change dimensions
  35.    Change type
  36.    Multiple matrix solve
  37.    Memory management
  38.    Output
  39.    Accessing matrices of unspecified type
  40.    Cholesky decomposition
  41.    Householder triangularisation
  42.    Singular Value Decomposition
  43.    Eigenvalues
  44.    Sorting
  45.    Fast Fourier Transform
  46.    Interface to Numerical Recipes in C
  47. List of files
  48. Notes on the design of the package
  49.    What this is package for
  50.    What size of matrices?
  51.    Allow matrix expressions?
  52.    Which matrix types?
  53.    What element types?
  54.    Naming convention
  55.    Row and Column index ranges
  56.    Structure of matrix objects
  57.    Data storage - one block or several
  58.    Data storage - by row or by column or other
  59.    Storage of symmetric matrices
  60.    Element access - method and checking
  61.    Use iterators?
  62.    Memory management - reference counting or status variable?
  63.    Evaluation of expressions - use two stage method?
  64.    How to overcome an explosion in number of operations
  65.    Using const
  66.    A calculus of matrix types
  67.    Error handling
  68.    Band and sparse matrices
  69. Problem report form
  70.  
  71.  
  72. ---------------------------------------------------------------------------
  73.  
  74.  
  75. General description
  76. ===================
  77.  
  78. The package is intented for scientists and engineers who need to
  79. manipulate a variety of types of matrices using standard matrix
  80. operations. Emphasis is on the kind of operations needed in statistical
  81. calculations such as least squares, linear equation solve and
  82. eigenvalues.
  83.  
  84. It supports matrix types
  85.  
  86.     Matrix                       (rectangular matrix)
  87.     nricMatrix                   (variant of rectangular matrix)
  88.     UpperTriangularMatrix
  89.     LowerTriangularMatrix
  90.     DiagonalMatrix
  91.     SymmetricMatrix
  92.     RowVector                    (derived from Matrix)
  93.     ColumnVector                 (derived from Matrix).
  94.  
  95. Only one element type (float or double) is supported.
  96.  
  97. The package includes the operations *, +, -, inverse, transpose,
  98. conversion between types, submatrix, determinant, Cholesky
  99. decomposition, Householder triangularisation, singular value
  100. decomposition, eigenvalues of a symmetric matrix, sorting, fast fourier
  101. transform, printing and an interface with "Numerical Recipes in C".
  102.  
  103. It is intended for matrices in the range 4 x 4 to about 90 x 90 (125 x
  104. 125 for triangular matrices). The upper limit is imposed by the maximum
  105. number of elements that can be contained in a single array (8192 doubles
  106. in some machines).
  107.  
  108. A two-stage approach to evaluating matrix expressions is used to improve
  109. efficiency and reduce use of temporary storage.
  110.  
  111. The package is designed for version 2 of C++. It works with Turbo C++,
  112. Borland C++, Glockenspiel C++ (2.00a) on a PC and AT&T C++ (2.0) and Gnu
  113. C++ on a Sun. It works with some problems with Zortech C++ (version 2).
  114.  
  115.  
  116. ---------------------------------------------------------------------------
  117.  
  118.  
  119. Is this the package you need?
  120. =============================
  121.  
  122. Do you
  123.  
  124. 1.   need matrix operators such as * and + defined as operators so you
  125.      can write things like
  126.  
  127.         X  = A * (B + C);
  128.  
  129. 2.   need a variety of types of matrices
  130.  
  131. 3.   need only one element type (float or double)
  132.  
  133. 4.   work with matrices in the range 4x4 to 90x90
  134.  
  135. 5.   tolerate a large and complex package
  136.  
  137.  
  138. Then maybe this is the right package for you. 
  139.  
  140. If you don't need (1) then there may be better options. Likewise if you
  141. don't need (2) there may be better options. If you require "not (5)"
  142. then this is not the package for you.
  143.  
  144.  
  145. If you need (2) and "not (3)" and have some spare money, then maybe you
  146. should look at M++ from Dyad or the Rogue Wave matrix package.
  147.  
  148.  
  149. ---------------------------------------------------------------------------
  150.  
  151.  
  152. Changes
  153. =======
  154.  
  155. Newmat03 - November 1991:
  156.  
  157. Col and Cols become Column and Columns. Added Sort, SVD, Jacobi,
  158. Eigenvalues, FFT, real conversion of 1x1 matrix, "Numerical Recipes in
  159. C" interface, output operations, various scalar functions. Improved
  160. return from functions. Reorganised setting options in "include.hxx".
  161.  
  162.  
  163. Newmat02 - July 1991:
  164.  
  165. Version with matrix row/column operations and numerous additional
  166. functions.
  167.  
  168.  
  169. Matrix - October 1990:
  170.  
  171. Early version of package.
  172.  
  173.  
  174. ---------------------------------------------------------------------------
  175.  
  176.  
  177. How to get a copy of this package
  178. =================================
  179.  
  180. I am putting copies on Compuserve (Borland library, zip format),
  181. SIMTEL20 (MsDos library, zip format), comp.sources.misc on Internet
  182. (shar format), and on the MsDos program library at Victoria University,
  183. Wellington.
  184.  
  185.  
  186. ---------------------------------------------------------------------------
  187.  
  188.  
  189. Compiler performance
  190. ====================
  191.  
  192. I have tested this package on a number of compilers. Here are the
  193. levels of success with this package. In most cases I have chosen code
  194. that works under all the compilers I have access to, but I have had to
  195. include some specific work-arounds for some compilers. For the MsDos
  196. versions, I am using a 386/387sx computer running MsDos 5, except that
  197. Turbo is on an old XT. The unix versions are on a Sun Sparc station.
  198.  
  199. A series of #defines at the beginning of "include.hxx" customises the
  200. package for the compiler you are using. Turbo, Borland and Zortech are
  201. recognised automatically, otherwise you have to set the appropriate
  202. #define statement.
  203.  
  204. The compilers are looking a bit old now. I do intend to test the package
  205. against newer versions as they become available.
  206.  
  207. Borland C++ 2.0: Recently, this has been my main development platform,
  208. so naturally almost everything works with this compiler. The library
  209. manager "tlib" fails but you can use "zorlib" from Zortech instead.
  210. Sometimes Borland crashes during a compiler or mis-compiles. You just
  211. have to reboot and continue the compile.
  212.  
  213. Turbo C++ (? version): Almost works OK. My rather elderly version does
  214. show a problem. Probably not worth tracking down - buy a newer version.
  215. Haven't tried the linker.
  216.  
  217. Zortech C++ 2.12: "const" doesn't work correctly with this compiler, so
  218. the package skips all of the statements Zortech can't handle. If you are
  219. using a later version of Zortech you could probably re-activate these
  220. statements. Zortech leaves rubbish on the heap. I don't know whether
  221. this is my programming error or a Zortech error. It works better when
  222. one doesn't optimise but there still are problems. The nric routines
  223. don't work. Zortech does not support IO manipulators.
  224.  
  225. Glockenspiel C++ (2.00a for MsDos loading into Microsoft C 5.1): I
  226. haven't tested the latest version of my package with Glockenspiel. I had
  227. to #define the matrix names to shorter names to avoid ambiguities and
  228. had quite a bit of difficulty stopping the compiles from running out of
  229. space and not exceeding Microsoft's block nesting limit. A couple of my
  230. test statements produced statements too complex for Microsoft, but
  231. basically the package worked. This was my original development platform
  232. and I still use .cxx and .hxx as my file name extensions. However,
  233. Glockenspiel is no longer competitive for MsDos and I am not updating my
  234. copy of the compiler.
  235.  
  236. Sun AT&T C++ 2.00: This works fine. Except aggregates are not supported.
  237.  
  238. Gnu G++ 1.37.1: This mostly works. You don't seem to be able to use
  239. expressions like Matrix(X*Y) in the middle of an expression and
  240. (Matrix)(X*Y) is unreliable. Gnu does not support IO manipulators. Gnu
  241. leaves rubbish on the heap. This is from output statements and not my
  242. package and may not be an error. The previous version of the package did
  243. not work under Gnu 1.37 or 1.39.
  244.  
  245.  
  246. ---------------------------------------------------------------------------
  247.  
  248. Example
  249. =======
  250.  
  251. An example is given in  example.cxx .  This gives a simple linear
  252. regression example using four different algorithms. The correct output
  253. is given in example.txt. The program carries out a check that no memory
  254. is left allocated on the heap when it terminates. The file  example.dep
  255. contains a dependency list for compiling  example.cxx . You will need to
  256. add the compile and link commands. example.dep lists all the files in
  257. the package so you can adapt for other projects. Don't forget to remove
  258. references to  newmat9.cxx  if you are using a compiler that does not
  259. support the standard io manipulators.
  260.  
  261.  
  262. ---------------------------------------------------------------------------
  263.  
  264.  
  265. Detailed Documentation
  266. ======================
  267.  
  268. Copyright (C) 1989,1990,1991: R B Davies and DSIR
  269.  
  270. Permission is granted to use but not to sell.
  271.  
  272.    --------------------------------------------------------------
  273.   | Please understand that this is a test version; there may     |
  274.   | still be bugs and errors. Use at your own risk. Neither I    |
  275.   | nor DSIR take any responsibility for any errors or omissions |
  276.   | in this package or for any misfortune that may befall you or |
  277.   | others as a result of its use.                               |
  278.    --------------------------------------------------------------
  279.  
  280. Please report bugs to me at
  281.  
  282.     robert@am.dsir.govt.nz
  283.  
  284. or
  285.  
  286.     Compuserve 72777,656
  287.  
  288. When reporting a bug please tell me which C++ compiler you are using (if
  289. known), and what version. Also give me details of your computer (if
  290. known). Tell me where you downloaded your version of my package from and
  291. its version number (eg newmat03 or newmat04). (There may be very minor
  292. differences between versions at different sites). Note any changes you
  293. have made to my code. If at all possible give me a piece of code
  294. illustrating the bug.
  295.  
  296. Please do report bugs to me.
  297.  
  298.  
  299. The matrix inverse routine and the sort routines are adapted from
  300. "Numerical Recipes in C" by Press, Flannery, Teukolsky, Vetterling,
  301. published by the Cambridge University Press.
  302.  
  303. Other code is adapted from routines in "Handbook for Automatic
  304. Computation, Vol II, Linear Algebra" by Wilkinson and Reinsch, published
  305. by Springer Verlag. 
  306.  
  307.  
  308. Customising
  309. -----------
  310.  
  311. I use .hxx as the suffix of definition files and .cxx as the suffix of
  312. C++ source files. This does not cause any problems with the compilers I
  313. use except that Borland and Turbo need to be told to accept any suffix
  314. as meaning a C++ file rather than a C file.
  315.  
  316. Use the large model when you are using a PC. Do not "outline" inline
  317. functions.
  318.  
  319. Each file accessing the matrix package needs to have file newmat.hxx 
  320. #included  at the beginning. Files using matrix applications (Cholesky
  321. decomposition, Householder triangularisation) need newmatap.hxx instead
  322. (or as well). If you need the output functions you will also need
  323. newmatio.hxx. Glockenspiel also needs to have include.hxx #included before
  324. newmat.hxx.
  325.  
  326. The file  include.hxx  sets the options for the compiler. If you are using
  327. a compiler different from one I have worked with you may have to set up
  328. a new section in  include.hxx  appropriate for your compiler.
  329.  
  330. Borland, Turbo and Zortech are recognised automatically. If you using
  331. Glockenspiel on a PC, AT&T, or Gnu C++ activate the appropriate
  332. statement at the beginning of include.hxx.
  333.  
  334. Activate the appropriate statement to make the element type float or
  335. double.
  336.  
  337. The file (newmat9.cxx) containing the output routines can be used only
  338. with libraries that support the AT&T input/output routines including
  339. manipulators. It cannot be used with Zortech or Gnu.
  340.  
  341.  
  342. Constructors
  343. ------------
  344.  
  345. To construct an m x n matrix, A, (m and n are integers) use
  346.  
  347.     Matrix A(m,n);
  348.  
  349. The UpperTriangularMatrix, LowerTriangularMatrix, SymmetricMatrix and
  350. DiagonalMatrix types are symmetric. To construct an n x n matrix use,
  351. for example
  352.  
  353.     UpperTriangularMatrix U(n);
  354.  
  355. Likewise the RowVector and ColumnVector types take just one argument in
  356. their constructors:
  357.  
  358.     RowVector RV(n);
  359.  
  360. You can also construct vectors and matrices without specifying the
  361. dimension. For example
  362.  
  363.     Matrix A;
  364.  
  365. In this case the dimension must be set by an assignment statement or a
  366. re-dimension statement.
  367.  
  368. You can also use a constructor to set a matrix equal to another matrix
  369. or matrix expression.
  370.  
  371.     Matrix A = U;
  372.  
  373.     Matrix A = U * L;
  374.  
  375. Only conversions that don't lose information are supported - eg you
  376. cannot convert an upper triangular matrix into a diagonal matrix using =.
  377.  
  378.  
  379. Elements of matrices
  380. --------------------
  381.  
  382. Elements are accessed by expressions of the form A(i,j) where i and j
  383. run from 1 to the appropriate dimension. Access elements of vectors with
  384. just one argument. Diagonal matrices can accept one or two subscripts.
  385.  
  386. This is different from the earlier version of the package in which the
  387. subscripts ran from 0 to one less than the appropriate dimension. Use
  388. A.element(i,j) if you want this earlier convention.
  389.  
  390.  
  391. Matrix copy
  392. -----------
  393.  
  394. The operator = is used for copying matrices, converting matrices, or
  395. evaluating expressions. For example
  396.  
  397.     A = B;  A = L;  A = L * U;
  398.  
  399. Only conversions that don't lose information are supported. The
  400. dimensions of the matrix on the left hand side are adjusted to those of
  401. the matrix or expression on the right hand side. Elements on the right
  402. hand side which are not present on the left hand side are set to zero.
  403.  
  404. The operator << can be used in place of = where it is permissible for
  405. information to be lost.
  406.  
  407. For example
  408.  
  409.     SymmetricMatrix S; Matrix A;
  410.     ......
  411.     S << A.t() * A;
  412.  
  413. is acceptable whereas
  414.  
  415.     S = A.t() * A;                            // error
  416.  
  417. will cause a runtime error since the package does not (yet) recognise
  418. A.t()*A as symmetric.
  419.  
  420. Note that you can not use << with constructors. For example
  421.  
  422.     SymmetricMatrix S << A.t() * A;           // error
  423.  
  424. does not work.
  425.  
  426. A third copy routine is used in a similar role to =. Use
  427.  
  428.     A.Inject(D);
  429.  
  430. to copy the elements of D to the corresponding elements of A but leave
  431. the elements of A unchanged if there is no corresponding element of D
  432. (the = operator would set them to 0). This is useful, for example, for
  433. setting the diagonal elements of a matrix without disturbing the rest of
  434. the matrix. Unlike = and <<, Inject does not reset the dimensions of A, which
  435. must match those of D.
  436.  
  437. Both << and Inject can be used with submatrix expressions on the left
  438. hand side. See the section on submatrices.
  439.  
  440. To set the elements of a matrix to a scalar use operator =
  441.  
  442.     real r; Matrix A(m,n);
  443.     ......
  444.     Matrix A(m,n); A = r;
  445.  
  446. You can load the elements of a matrix from an array:
  447.  
  448.     Matrix A(3,2);
  449.     real a[] = { 11,12,21,22,31,33 };
  450.     A << a;
  451.  
  452. This construction cannot check that the numbers of elements match
  453. correctly. This version of << can be used with submatrices on the left
  454. hand side.
  455.  
  456.  
  457. Unary operators
  458. ---------------
  459.  
  460. The package supports unary operations
  461.  
  462.     change sign of elements            -A
  463.     transpose                          A.t()
  464.     inverse (of square matrix A)       A.i()
  465.  
  466.  
  467. Binary operations
  468. -----------------
  469.  
  470. The package supports binary operations
  471.  
  472.     matrix addition                    A+B
  473.     matrix subtraction                 A-B
  474.     matrix multiplication              A*B
  475.     equation solve (square matrix A)   A.i()*B
  476.  
  477. In the last case the inverse is not calculated.
  478.  
  479. Notes:
  480.  
  481. If you are doing repeated multiplication. For example A*B*C, use
  482. brackets to force the order to minimize the number of operations. If C
  483. is a column vector and A is not a vector, then it will usually reduce
  484. the number of operations to use A*(B*C) .
  485.  
  486. The package does not recognise B*A.i() as an equation solve. It is
  487. probably better to use (A.t().i()*B.t()).t() .
  488.  
  489.  
  490. Combination of a matrix and scalar
  491. ----------------------------------
  492.  
  493. The following expression multiplies the elements of a matrix A by a
  494. scalar f:  A * f; Likewise one can divide the elements of a matrix A by
  495. a scalar f:  A / f;
  496.  
  497. The expressions  A + f and A - f add or subtract a rectangular matrix of
  498. the same dimension as A with elements equal to f to or from the matrix
  499. A.
  500.  
  501. In each case the matrix must be the first term in the expression.
  502. Expressions such  f + A  or  f * A  are not recognised.
  503.  
  504.  
  505. Scalar functions of matrices
  506. ----------------------------
  507.             
  508.     int m = A.Nrows();                    // number of rows
  509.     int n = A.Ncols();                    // number of columns
  510.     real ssq = A.SumSquare();             // sum of squares of elements
  511.     real sav = A.SumAbsoluteValue();      // sum of absolute values
  512.     real mav = A.MaximumAbsoluteValue();  // maximum of absolute values
  513.     real norm = A.Norm1();                // maximum of sum of absolute
  514.                                              values of elements of a column
  515.     real norm = A.NormInfinity();         // maximum of sum of absolute
  516.                                              values of elements of a row
  517.     real t = A.Trace();                   // trace
  518.     LogandSign ld = A.LogDeterminant();   // log of determinant
  519.     BOOL z = A.IsZero();                  // test all elements zero
  520.     MatrixType mt = A.Type();             // type of matrix
  521.     real* s = Store();                    // pointer to array of elements
  522.     int l = Storage();                    // length of array of elements
  523.  
  524. A.LogDeterminant() returns a value of type LogandSign. If ld is of type 
  525. LogAndSign  use
  526.  
  527.     ld.Value()    to get the value of the determinant
  528.     ld.Sign()     to get the sign of the determinant (values 1, 0, -1)
  529.     ld.LogValue() to get the log of the absolute value.
  530.  
  531. A.IsZero() returns BOOL value TRUE if the matrix A has all elements
  532. equal to 0.0.
  533.  
  534. MatrixType mt = A.Type() returns the type of a matrix. Use (char*)mt to
  535. get a string  (UT, LT, Rect, Sym, Diag, RowV, ColV, Crout) showing the
  536. type.
  537.  
  538. SumSquare(A), SumAbsoluteValue(A), MaximumAbsoluteValue(A), Trace(A),
  539. LogDeterminant(A), Norm1(A), NormInfinity(A)  can be used in place of
  540. A.SumSquare(), A.SumAbsoluteValue(), A.MaximumAbsoluteValue(),
  541. A.Trace(), A.LogDeterminant(), A.Norm1(), A,NormInfinity().
  542.  
  543.  
  544. Submatrix operations
  545. --------------------
  546.  
  547. A.SubMatrix(fr,lr,fc,lc)
  548.  
  549. This selects a submatrix from A. the arguments  fr,lr,fc,lc  are the
  550. first row, last row, first column, last column of the submatrix with the
  551. numbering beginning at 1. This may be used in any matrix expression or
  552. on the left hand side of << or Inject. Inject does not check no
  553. information loss in this case. You can also use the construction
  554.  
  555.     real c; .... A.SubMatrix(fr,lr,fc,lc) << c;
  556.  
  557. to set a submatrix equal to a constant.
  558.  
  559. The follwing are variants of SubMatrix:
  560.  
  561.     A.SymSubMatrix(f,l)             //   This assumes fr=fc and lr=lc.
  562.     A.Rows(f,l)                     //   select rows
  563.     A.Row(f)                        //   select single row
  564.     A.Columns(f,l)                  //   select columns
  565.     A.Column(f)                     //   select single column
  566.  
  567. In each case f and l mean the first and last row or column to be
  568. selected (starting at 1).
  569.  
  570. If SubMatrix or its variant occurs on the right hand side of an = or <<
  571. or within an expression its type is as follows
  572.  
  573.     A.Submatrix(fr,lr,fc,lc):           If A is RowVector or
  574.                                         ColumnVector then same type
  575.                                         otherwise type Matrix
  576.     A.SymSubMatrix(f,l):                Same type as A
  577.     A.Rows(f,l):                        Type Matrix
  578.     A.Row(f):                           Type RowVector
  579.     A.Columns(f,l):                     Type Matrix
  580.     A.Column(f):                        Type ColumnVector
  581.  
  582.  
  583. If SubMatrix or its variant appears on the left hand side of  << , think
  584. of its type being Matrix. Thus L.Row(1) where L is LowerTriangularMatrix
  585. expects  L.Ncols()  elements even though it will use only one of them.
  586.  
  587.  
  588. Change dimensions
  589. -----------------
  590.  
  591. The following operations change the dimensions of a matrix. The values
  592. of the elements are lost.
  593.  
  594.     A.ReDimension(nrows,ncols);     // for type Matrix or nricMatrix
  595.     A.ReDimension(n);               // for all other types
  596.  
  597.  
  598. Change type
  599. -----------
  600.  
  601. The following functions interpret the elements of a matrix
  602. (stored row by row) to be a vector or matrix of a different type. Actual
  603. copying is usually avoided where these occur as part of a more
  604. complicated expression.
  605.  
  606.     A.CopyToRow()
  607.     A.CopyToColumn()
  608.     A.CopyToDiagonal()
  609.     A.CopyToMatrix(nrows,ncols)
  610.     A.c()
  611.     real(A)
  612.  
  613. The form .c() is used in matrix expressions when A is of a const
  614. type. The expression real(A) is used to convert a 1 x 1 matrix to a
  615. scalar.
  616.  
  617.  
  618. Multiple matrix solve
  619. ---------------------
  620.  
  621. If A is a square or symmetric matrix use
  622.  
  623.     CroutMatrix X = A;                // carries out LU decomposition
  624.     Matrix AP = X.i()*P; Matrix AQ = X.i()*Q;
  625.     LogAndSign ld = X.LogDeterminant();
  626.  
  627. rather than
  628.  
  629.     Matrix AP = A.i()*P; Matrix AQ = A.i()*Q;
  630.     LogAndSign ld = A.LogDeterminant();
  631.  
  632. since each operation will repeat the LU decompostion.
  633.  
  634.  
  635. Memory management
  636. -----------------
  637.  
  638. The package does not support delayed copy. Several strategies are
  639. required to prevent unnecessary matrix copies.
  640.  
  641. Where a matrix is called as a function argument use a constant
  642. reference. For example
  643.  
  644.     YourFunction(const Matrix& A)
  645.  
  646. rather than
  647.  
  648.     YourFunction(Matrix A)
  649.  
  650. Constant matrices cannot be used in matrix expressions so if you wish to
  651. use A in an expression within this function use A.c() rather than A.
  652.  
  653. Skip the rest of this section on your first reading.
  654.  
  655. A second place where it is desirable to avoid unnecessary copies is when
  656. a function is returning a matrix. Matrices can be returned from a
  657. function with the return command as you would expect. However these may
  658. incur one and possibly two copyings of the matrix. To avoid this use the
  659. following instructions.
  660.  
  661. Make your function of type  ReturnMatrix . Then precede the return
  662. statement with a Release statement (or a ReleaseAndDelete statement if
  663. the matrix was created with new). For example
  664.  
  665.  
  666.     ReturnMatrix MakeAMatrix()
  667.     {
  668.        Matrix A;
  669.        ......
  670.        A.Release(); return A;
  671.     }
  672.  
  673. or
  674.  
  675.     ReturnMatrix MakeAMatrix()
  676.     {
  677.        Matrix* m = new Matrix;
  678.        ......
  679.        m->ReleaseAndDelete(); return *m;
  680.     }
  681.  
  682. Note that .c() cannot be applied to a matrix following application of
  683. .Release() or ->ReleaseAndDelete() .
  684.  
  685.  --------------------------------------------------------------------- 
  686. | Do not forget to make the function of type ReturnMatrix; otherwise  |
  687. | incomprehensible run-time errors will occur with some compilers.    |
  688.  --------------------------------------------------------------------- 
  689.  
  690. You can also use .Release() or ->ReleaseAndDelete() to allow a matrix
  691. expression to recycle space. Suppose you call
  692.  
  693.     A.Release();
  694.  
  695. just before A is used just once in an expression. Then the memory used
  696. by A is either returned to the system or reused in the expression. In
  697. either case, A's memory is destroyed. This procedure can be used to
  698. imporve efficiency and reduce the use of memory.
  699.  
  700. Use ->ReleaseAndDelete for matrices created by new if you want to
  701. completely delete the matrix after it is accessed.
  702.  
  703.  
  704. Output
  705. ------
  706.  
  707. To print a matrix use an expression like
  708.  
  709.     Matrix A;
  710.     ......
  711.     cout << setw(10) << setprecision(5) << A;
  712.  
  713. This will work only with systems that support the AT&T input/output
  714. routines including manipulators.
  715.  
  716.  
  717. Accessing matrices of unspecified type
  718. --------------------------------------
  719.  
  720. Skip this section on your first reading.
  721.  
  722. Suppose you wish to write a function which accesses a matrix of unknown
  723. type including expressions (eg A*B). Then use a layout similar to the
  724. following:
  725.  
  726.    void YourFunction(BaseMatrix& X)
  727.    {
  728.       GeneralMatrix* gm = X.Evaluate();   // evaluate an expression
  729.                                           // if necessary
  730.       ........                            // operations on *gm
  731.       gm->tDelete();                      // delete *gm if a temporary
  732.    }
  733.  
  734. See, as an example, the definitions of operator<< in newmat9.cxx.
  735.  
  736.  
  737. Cholesky decomposition
  738. ----------------------
  739.  
  740. Suppose S is symmetric and positive definite. Then there exists a unique
  741. lower triangular matrix L such that L * L.t() = S. To calculate this use
  742.  
  743.     SymmetricMatrix S;
  744.     ......
  745.     LowerTriangularMatrix L = Cholesky(S);
  746.  
  747.  
  748. Householder triangularisation
  749. -----------------------------
  750.  
  751. Start with matrix
  752.  
  753.        / X    0 \      s
  754.        \ Y    0 /      t
  755.  
  756.          n    s
  757.  
  758. The Householder triangularisation post multiplies by an orthogonal
  759. matrix Q such that the matrix becomes
  760.  
  761.        / 0    L \      s
  762.        \ Z    M /      t
  763.  
  764.          n    s
  765.  
  766. where L is lower triangular. Note that X is the transpose of the matrix
  767. sometimes considered in this context.
  768.  
  769. This is good for solving least squares problems: choose b (matrix or row
  770. vector) to minimize the sum of the squares of the elements of
  771.  
  772.          Y - b*X
  773.  
  774. Then choose b = M * L.i();
  775.  
  776. Two routines are provided:
  777.  
  778.     HHDecompose(X, L);
  779.  
  780. replaces X by orthogonal columns and forms L.
  781.  
  782.     HHDecompose(X, Y, M);
  783.  
  784. uses X from the first routine, replaces Y by Z and forms M.
  785.  
  786.  
  787. Singular Value Decomposition
  788. ----------------------------
  789.  
  790. The singular value decomposition of an m x n matrix A ( where m >= n) is
  791. a decomposition
  792.  
  793.     A  = U * D * V.t()
  794.  
  795. where U is m x n with  U.t() * U  equalling the identity, D is an n x n
  796. diagonal matrix and V is an n x n orthogonal matrix.
  797.  
  798. Singular value decompositions are useful for understanding the structure
  799. of ill-conditioned matrices, solving least squares problems, and for
  800. finding the eigenvalues of A.t() * A.
  801.  
  802. To calculate the singular value decomposition of A (with m >= n) use one
  803. of
  804.  
  805.     SVD(A, D, U, V);                  // U (= A is OK)
  806.     SVD(A, D);
  807.     SVD(A, D, U);                     // U (= A is OK)
  808.     SVD(A, D, U, FALSE);              // U (can = A) for workspace only
  809.     SVD(A, D, U, V, FALSE);           // U (can = A) for workspace only
  810.  
  811. The values of A are not changed unless A is also inserted as the third
  812. argument.
  813.  
  814.  
  815. Eigenvalues
  816. -----------
  817.  
  818. An eigenvalue decomposition of a symmetric matrix A is a decomposition
  819.  
  820.     A  = V * D * V.t()
  821.  
  822. where V is an orthogonal matrix and D is a diagonal matrix.
  823.  
  824. Eigenvalue analyses are used in a wide variety of engineering,
  825. statistical and other mathematical analyses.
  826.  
  827. The package includes two algorithms: Jacobi and Householder. The first
  828. is extremely reliable but much slower than the second.
  829.  
  830. The code is adapted from routines in "Handbook for Automatic
  831. Computation, Vol II, Linear Algebra" by Wilkinson and Reinsch, published
  832. by Springer Verlag. 
  833.  
  834.  
  835.     Jacobi(A,D,S,V);                  // A, S symmetric is for workspace,
  836.                                       //    S = A is OK
  837.     Jacobi(A,D);                      // A symmetric
  838.     Jacobi(A,D,S);                    // A, S symmetric is for workspace,
  839.                                       //    S = A is OK
  840.     Jacobi(A,D,V);                    // A symmetric
  841.  
  842.     EigenValues(A,D);                 // A symmetric
  843.     EigenValues(A,D,S);               // A, S symmetric is for back
  844.                                       //    transforming, S = A is OK
  845.     EigenValues(A,D,V);               // A symmetric
  846.  
  847.  
  848. Sorting
  849. -------
  850.  
  851. To sort the values in a matrix or vector, A, (in general this operation
  852. makes sense only for vectors and diagonal matrices) use
  853.  
  854.     SortAscending(A);
  855.  
  856. or
  857.  
  858.     SortDescending(A);
  859.  
  860.  
  861. Fast Fourier Transform
  862. ----------------------
  863.  
  864. FFT(CV1, CV2, CV3, CV4);       // CV3=CV1 and CV4=CV2 is OK
  865.  
  866. where CV1, CV2, CV3, CV4 are column vectors. CV1 and CV2 are the real
  867. and imaginary input vectors; CV3 and CV4 are the real and imaginary
  868. output vectors. The lengths of CV1 and CV2 must be equal and should be
  869. the product of numbers less than about 10 for fast execution.
  870.  
  871.  
  872. Interface to Numerical Recipes in C
  873. -----------------------------------
  874.  
  875. This package can be used with the vectors and matrices defined in
  876. "Numerical Recipes in C". You need to edit the routines in Numerical
  877. Recipes so that the elements are of the same type as used in this
  878. package. Eg replace float by double, vector by dvector and matrix by
  879. dmatrix, etc. You will also need to edit the function definitions to use
  880. the version acceptable to your compiler. Then enclose the code from
  881. Numerical Recipes in  extern "C" { ... }. You will also need to include
  882. the matrix and vector utility routines.
  883.  
  884. Then any vector in Numerical Recipes with subscripts starting from 1 in
  885. a function call can be replaced by a RowVector, ColumnVector or
  886. DiagonalMatrix in the present package. Similarly any matrix with
  887. subscripts starting from 1 can be replaced by an  nricMatrix  in the
  888. present package. The class nricMatrix is derived from Matrix and can be
  889. used in place of Matrix.
  890.  
  891. Numerical Recipes cannot change the dimensions of a matrix or vector. So
  892. matrices or vectors must be correctly dimensioned before a Numerical
  893. Recipes routine is called.
  894.  
  895. For example
  896.  
  897.    SymmetricMatrix B(44);
  898.    .....                             // load values into B
  899.    nricMatrix BX = B;                // copy values to an nricMatrix
  900.    DiagonalMatrix D(44);             // Matrices for output
  901.    nricMatrix V(44,44);              //    correctly dimensioned
  902.    int nrot;
  903.    jacobi(BX,44,D,V,&nrot);          // jacobi from NRIC
  904.    cout << D;                        // print eigenvalues
  905.  
  906. ---------------------------------------------------------------------------
  907.  
  908.  
  909. List of files
  910. =============
  911.  
  912. README          readme file
  913. NEWMAT   TXT    documentation file
  914. NEWMAT   LIS    list of files
  915. CLASS    TXT    list of classes
  916.  
  917. BOOLEAN  HXX    boolean class definition
  918. CONTROLW HXX    control word definition file
  919. INCLUDE  HXX    details of include files and options
  920. NEWMAT   HXX    main matrix clss definition file
  921. NEWMATAP HXX    applications definition file
  922. NEWMATIO HXX    input/output definition file
  923. NEWMATRC HXX    row/column functions definition files
  924. NEWMATRM HXX    rectangular matrix access definition files
  925. PRECISIO HXX    numerical precision constants
  926.  
  927. CHOLESKY CXX    Cholesky decomposition
  928. EVALUE   CXX    eigenvalues and eigenvector calculation
  929. FFT      CXX    fast Fourier transform
  930. HHOLDER  CXX    Householder triangularisation
  931. JACOBI   CXX    eigenvalues by the Jacobi method
  932. NEWMAT1  CXX    type manipulation routines
  933. NEWMAT2  CXX    row and column manipulation functions
  934. NEWMAT3  CXX    row and column access functions
  935. NEWMAT4  CXX    constructors, redimension, utilities
  936. NEWMAT5  CXX    transpose, evaluate, matrix functions
  937. NEWMAT6  CXX    operators, element access
  938. NEWMAT7  CXX    invert, solve, binary operations
  939. NEWMAT8  CXX    LU decomposition, scalar functions
  940. NEWMAT9  CXX    output routines
  941. NEWMATRM CXX    rectangular matrix access functions
  942. SORT     CXX    sorting functions
  943. SUBMAT   CXX    submatrix functions
  944. SVD      CXX    singular value decomposition
  945.  
  946. EXAMPLE  CXX    example of use of package
  947. EXAMPLE  TXT    output from example
  948. EXAMPLE  DEP    dependency file for example
  949.  
  950. ---------------------------------------------------------------------------
  951.  
  952.  
  953. Notes on the design of the package
  954. ==================================
  955.  
  956. Copyright (C) 1991: R B Davies and DSIR
  957.  
  958. Please treat this as an academic publication. You can use the ideas but
  959. please acknowledge in any publication.
  960.  
  961.  
  962. In this section, I describe some of the ideas behind this package, some
  963. of the decisions that I needed to make and give some details about the
  964. way it works. You don't need to read this section in order to use the
  965. package.
  966.  
  967. I don't think it is obvious what is the best way of going about
  968. structuring a matrix package. And I don't think you can figure this
  969. out with "thought" experiments. Different people have to try out
  970. different approaches. And someone else may have to figure out which is
  971. best. Or, more likely, the ultimate packages will lift some ideas from
  972. each of a variety of trial packages. So, I don't claim my package is an
  973. "ultimate" package, but simply a trial of a number of ideas.
  974.  
  975. But I do hope it will meet the immediate requirements of some people who
  976. need to carry out matrix calculations.
  977.  
  978.  
  979. What this is package for
  980. ------------------------
  981.  
  982. The package is used for the manipulation of matrices, including the
  983. standard operations such as multiplication as understood by numerical
  984. analysts, engineers and mathematicians. A matrix is a two dimensional
  985. array of numbers. However, very special operations such as matrix
  986. multiplication are defined specifically for matrices. This means that a
  987. "matrix" package tends to be different from a general "array" package.
  988.  
  989. I see a matrix package as providing the following
  990.  
  991. 1.   Evaluation of matrix expressions in a form familiar to
  992.      scientists and engineers. For example  A = B * (C + D.t());
  993. 2.   Access to the elements of a matrix;
  994. 3.   Access to submatrices;
  995. 4.   Common elementary matrix functions such as determinant and trace;
  996. 5.   A platform for developing advanced matrix functions such as eigen-
  997.      value analysis;
  998. 6.   Good efficiency and storage management;
  999. 7.   Graceful exit from errors (I don't provide this yet).
  1000.  
  1001. It may also provide
  1002.  
  1003. 8.   A variety of types of elements (eg real and complex);
  1004. 9.   A variety of types of matrices (eg rectangular and symmetric).
  1005.  
  1006. In contrast an array package should provide
  1007.  
  1008. 1'.  Arrays can be copied with a single instruction; may have some
  1009.      arithmetic operations, say + - and scalar + - * /, it may provide
  1010.      matrix multiplication as a function;
  1011. 2'.  High speed access to elements directly and with iterators;
  1012. 3'.  Access to subarrays and rows (and columns?);
  1013. 6'.  Good efficiency and storage management;
  1014. 7'.  Graceful exit from errors;
  1015. 8'.  A variety of types of elements (eg real and complex);
  1016. 9'.  One, two and three dimensional arrays, at least, with starting
  1017.      points of the indices set by user; may have arrays with ragged
  1018.      rows.
  1019.  
  1020. It may be possible to amalgamate these two sets of requirements to some
  1021. extent. However my package is definitely oriented towards the first set.
  1022.  
  1023. Even within the bounds set by the first set of requirements there is a
  1024. substantial opportunity for variation between what different matrix
  1025. packages might provide.
  1026.  
  1027. It is not possible to build a matrix package that will meet everyone's
  1028. requirements. In many cases if you put in one facility, you impose
  1029. overheads on everyone using the package. This both is storage required
  1030. for the program and in efficiency. Likewise a package that is optimised
  1031. towards handling large matrices is likely to become less efficient for
  1032. very small matrices where the administration time for the matrix may
  1033. become significant compared with the time to carry out the operations.
  1034.  
  1035. It is better to provide a variety of packages (hopefully compatible) so
  1036. that most users can find one that meets their requirements. This package
  1037. is intended to be one of these packages; but not all of them.
  1038.  
  1039. Since my background is in statistical methods, this package is oriented
  1040. towards the kinds things you need for statistical analyses.
  1041.  
  1042.  
  1043. What size of matrices?
  1044. ----------------------
  1045.  
  1046. A matrix package may target small matrices (say 3 x 3), or medium sized
  1047. matrices, or very large matrices. A package targeting very small
  1048. matrices will seek to minimise administration. A package for medium
  1049. sized or very large matrices can spend more time on administration in
  1050. order to conserve space or optimise the evaluation of expressions. A
  1051. package for very large matrices will need to pay special attention to
  1052. storage and numerical properties.
  1053.  
  1054. This package is designed for medium sized matrices. This means it is
  1055. worth introducing some optimisations, but I don't have to worry about
  1056. the 64K limit that some compilers impose.
  1057.  
  1058.  
  1059. Allow matrix expressions?
  1060. -------------------------
  1061.  
  1062. I want to be able to write matrix expressions the way I would on paper.
  1063. So if I want to multiply two matrices and then add the transpose of a
  1064. third one I can write something like
  1065.  
  1066.    X = A * B + C.t();
  1067.  
  1068. I want this expression to be evaluated with close to the same efficiency
  1069. as a hand-coded version. This is not so much of a problem with
  1070. expressions including a multiply since the multiply will dominate the
  1071. time. However, it is not so easy to achieve with expressions with just +
  1072. and - .
  1073.  
  1074. A second requirement is that temporary matrices generated during the
  1075. evaluation of an expression are destroyed as quickly as possible.
  1076.  
  1077. A desirable feature is that a certain amount of "intelligence" be
  1078. displayed in the evaluation of an expression. For example, in the
  1079. expression
  1080.  
  1081.    X = A.i() * B;
  1082.  
  1083. where i() denotes inverse, it would be desirable if the inverse wasn't
  1084. explicitly calculated.
  1085.  
  1086.  
  1087. Which matrix types?
  1088. -------------------
  1089.  
  1090. As well as the usual rectangular matrices, matrices occuring repeatedly
  1091. in numerical calculations are upper and lower triangular matrices,
  1092. symmetric matrices and diagonal matrices. This is particularly the case
  1093. in calculations involving least squares and eigenvalue calculations. So
  1094. as a first stage these were the types I decided to include.
  1095.  
  1096. It is also necessary to have types row vector and column vector. In a
  1097. "matrix" package, in contrast to an "array" package, it is necessary to
  1098. have both these types since they behave differently in matrix
  1099. expressions. The vector types can be derived for the rectangular matrix
  1100. type, so having them does not greatly increase the complexity of the
  1101. package.
  1102.  
  1103. The problem with having several matrix types is the number of versions
  1104. of the binary operators one needs. If one has 5 distinct matrix types
  1105. then a simple package will need 25 versions of each of the binary
  1106. operators. In fact, we can evade this problem, but at the cost of some
  1107. complexity.
  1108.  
  1109.  
  1110. What element types?
  1111. -------------------
  1112.  
  1113. Ideally we would allow element types double, float, complex and int, at
  1114. least. It would be reasonably easy, using templates or equivalent, to
  1115. provide a package which could handle a variety of element types.
  1116. However, as soon as one starts implementing the binary operators between
  1117. matrices with different element types, again one gets an explosion in
  1118. the number of operations one needs to consider. Hence I decided to
  1119. implement only one element type. But the user can decide whether this is
  1120. float or double. The package assumes elements are of type real. The user
  1121. typedefs to float or double.
  1122.  
  1123. In retrospect, it would not be too hard to include matrices with complex
  1124. matrix type.
  1125.  
  1126. It might also be worth including symmetric and triangular matrices with
  1127. extra precision elements (double or long double) to be used for storage
  1128. only and with a minimum of operations defined. These would be used for
  1129. accumulating the results of sums of squares and product matrices or
  1130. multistage Householder triangularisations.
  1131.  
  1132.  
  1133. Naming convention
  1134. -----------------
  1135.  
  1136. How are classes and public member functions to be named? As a general
  1137. rule I have spelt identifiers out in full with individual words being
  1138. capitalised. For example "UpperTriangularMatrix". If you don't like this
  1139. you can #define or typedef shorter names. This convention means you can
  1140. select an abbreviation scheme that makes sense to you.
  1141.  
  1142. The convention causes problems for Glockenspiel C++ on a PC feeding into
  1143. Microsoft C. The names Glockenspiel generates exceed the the 32
  1144. characters recognised by Microsoft C and ambiguities result. So it is
  1145. necessary to #define shorter names.
  1146.  
  1147. Exceptions to the general rule are the functions for transpose and
  1148. inverse. To make matrix expressions more like the corresponding
  1149. mathematical formulae, I have used the single letter abbreviations, t()
  1150. and i() .
  1151.  
  1152.  
  1153. Row and Column index ranges
  1154. ---------------------------
  1155.  
  1156. In mathematical work matrix subscripts usually start at one. In C, array
  1157. subscripts start at zero. In Fortran, they start at one. Possibilities
  1158. for this package were to make them start at 0 or 1 or be arbitrary.
  1159. Alternatively one could specify an "index set" for indexing the rows and
  1160. columns of a matrix. One would be able to add or multiply matrices only
  1161. if the appropriate row and column index sets were identical.
  1162.  
  1163. In fact, I adopted the simpler convention of making the rows and columns
  1164. of a matrix be indexed by an integer starting at one, following the
  1165. traditional convention. In an earlier version of the package I had them
  1166. starting at zero, but even I was getting mixed up when trying to use
  1167. this earlier package. So I reverted to the more usual notation.
  1168.  
  1169.  
  1170. Structure of matrix objects
  1171. ---------------------------
  1172.  
  1173. Each matrix object contains the basic information such as the number of
  1174. rows and columns and a status variable plus a pointer to the data
  1175. array which is on the heap.
  1176.  
  1177.  
  1178. Data storage - one block or several
  1179. -----------------------------------
  1180.  
  1181. In this package the elements of the matrix are stored as a single array.
  1182. Alternatives would have been to store each row as a separate array or a
  1183. set of adjacent rows as a separate array. The present solution
  1184. simplifies the program but limits the size of matrices in systems that
  1185. have a 64k byte (or other) limit on the size of arrays. The large arrays
  1186. may also cause problems for memory management in smaller machines.
  1187.  
  1188.  
  1189. Data storage - by row or by column or other
  1190. -------------------------------------------
  1191.  
  1192. In Fortran two dimensional arrays are stored by column. In most other
  1193. systems they are stored by row. I have followed this later convention.
  1194. This makes it easier to interface with other packages written in C but
  1195. harder to interface with those written in Fortran.
  1196.  
  1197. An alternative would be to store the elements by mid-sized rectangular
  1198. blocks. This might impose less strain on memory management when one
  1199. needs to access both rows and columns.
  1200.  
  1201.  
  1202. Storage of symmetric matrices
  1203. -----------------------------
  1204.  
  1205. Symmetric matrices are stored as lower triangular matrices. The decision
  1206. was pretty arbitrary, but it does slightly simplify the Cholesky
  1207. decomposition program.
  1208.  
  1209.  
  1210. Element access - method and checking
  1211. ------------------------------------
  1212.  
  1213. We want to be able to use the notation A(i,j) to specify the (i,j)-th
  1214. element of a matrix. This is the way mathematicians expect to address
  1215. the elements of matrices. I didn't even consider using the totally alien
  1216. notation A[i][j]. There are two ways of working out the address of
  1217. A(i,j). One is using a "dope" vector which contains the first address of
  1218. each row. This is how C works when you use A[i][j]. Alternatively you
  1219. can calculate the address using the formula appropriate for the
  1220. structure of A. I use this second approach. It is probably slower, but
  1221. saves worrying about an extra bit of storage. The other question is
  1222. whether to check for i and j being in range. I do carry out this check
  1223. following years of experience with both systems that do and systems that
  1224. don't do this check.
  1225.  
  1226. I would hope that the routines I supply with this package will reduce
  1227. your need to access elements of matrices so speed of access is not a
  1228. high priority.
  1229.  
  1230.  
  1231. Use iterators?
  1232. --------------
  1233.  
  1234. Iterators are an alternative way of providing fast access to the
  1235. elements of an array or matrix when they are to be accessed
  1236. sequentially. They need to be customised for each type of matrix. I have
  1237. not implemented iterators in this package, although some iterator like
  1238. functions are used for some row and column functions.
  1239.  
  1240.  
  1241. Memory management - reference counting or status variable?
  1242. ----------------------------------------------------------
  1243.  
  1244. Consider the instruction
  1245.  
  1246.    X = A + B + C;
  1247.  
  1248. To evaluate this a simple program will add A to B putting the total in a
  1249. temporary T1. Then it will add T1 to C creating another temporary T2
  1250. which will be copied into X. T1 and T2 will sit around till the end of
  1251. the block. It would be faster if the program recognised that T1 was
  1252. temporary and stored the sum of T1 and C back into T1 instead of
  1253. creating T2 and then avoided the final copy by just assigning the
  1254. contents of T1 to X rather than copying. In this case there will be no
  1255. temporaries requiring deletion. (More precisely there will be a header
  1256. to be deleted but no contents).
  1257.  
  1258. For an instruction like
  1259.  
  1260.    X = (A * B) + (C * D);
  1261.  
  1262. we can't avoid one temporary being left over, so we would like this
  1263. temporary deleted as quickly as possible.
  1264.  
  1265. I provide the functionality for doing this by attaching a status
  1266. variable to each matrix. This indicates if the matrix is temporary so
  1267. that its memory is available for recycling or deleting. Any matrix
  1268. operation checks the status variables of the matrices it is working with
  1269. and recycles or deletes any temporary memory.
  1270.  
  1271. An alternative or additional approach would be to use delayed copying.
  1272. If a program requests a matrix to be copied, the copy is delayed until
  1273. an instruction is executed which modifies the memory of either the
  1274. original matrix or the copy. This saves the unnecessary copying in the
  1275. previous examples. However, it does not provide the additional
  1276. functionality of my approach.
  1277.  
  1278. It would be possible to have both delayed copy and tagging temporaries,
  1279. but this seemed an unnecessary complexity. In particular delayed copy
  1280. mechanisms seem to require two calls to the heap manager, using extra
  1281. time and making building a memory compacting mechanism more difficult.
  1282.  
  1283.  
  1284. Evaluation of expressions - use two stage method?
  1285. -------------------------------------------------
  1286.  
  1287. Consider the instruction
  1288.  
  1289.    X = B - X;
  1290.  
  1291. The simple program will subtract X from B, store the result in a
  1292. temporary T1 and copy T1 into X. It would be faster if the program
  1293. recognised that the result could be stored directly into X. This would
  1294. happen automatically if the program could look at the instruction first
  1295. and mark X as temporary.
  1296.  
  1297. C programmers would expect to avoid the same problem with
  1298.  
  1299.    X = X - B;
  1300.  
  1301. by using an operator -= (which I haven't provided, yet)
  1302.  
  1303.    X -= B;
  1304.  
  1305. However this is an unnatural notation for non C users and it is much
  1306. nicer to write
  1307.  
  1308.    X = X - B;
  1309.  
  1310. and know that the program will carry out the simplification.
  1311.  
  1312. Another example where this intelligent analysis of an instruction is
  1313. helpful is in
  1314.  
  1315.    X = A.i() * B;
  1316.  
  1317. where i() denotes inverse. Numerical analysts know it is inefficient to
  1318. evaluate this expression by carrying out the inverse operation and then
  1319. the multiply. Yet it is a convenient way of writing the instruction. It
  1320. would be helpful if the program recognised this expression and carried
  1321. out the more appropriate approach.
  1322.  
  1323. To carry out this "intelligent" analysis of an instruction  matrix
  1324. expressions are evaluated in two stages. In the the first stage a tree
  1325. representation of the expression is formed.
  1326.  
  1327. For example (A+B)*C is represented by a tree
  1328.  
  1329.                     *
  1330.                    / \
  1331.                   +   C
  1332.                  / \
  1333.                 A   B
  1334.  
  1335. Rather than adding A and B the + operator yields an object of a class
  1336. "AddedMatrix" which is just a pair of pointers to A and B. Then the *
  1337. operator yields a "MultipliedMatrix" which is a pair of pointers to the
  1338. "AddedMatrix" and C. The tree is examined for any simplifications and
  1339. then evaluated recursively.
  1340.  
  1341. Further possibilities not yet included are to recognise A.t()*A and
  1342. A.t()+A as symmetric or to improve the efficiency of evaluation of
  1343. expressions like A+B+C, A*B*C, A*B.t()  [t() denotes transpose].
  1344.  
  1345. One of the disadvantages of the two-stage approach is that the types of
  1346. matrix expressions are determined at run-time. So the compiler will not
  1347. detect errors of the type
  1348.  
  1349.    Matrix M; DiagonalMatrix D; ....; D = M;
  1350.  
  1351. We don't allow conversions using = when information would be lost. Such
  1352. errors will be detected when the statement is executed.
  1353.  
  1354.  
  1355. How to overcome an explosion in number of operations
  1356. ----------------------------------------------------
  1357.  
  1358. The package attempts to solve the problem of the large number of
  1359. versions of the binary operations required when one has a variety of
  1360. types. With n types of matrices the binary operations will each require
  1361. n-squared separate algorithms. Some reduction in the number may be
  1362. possible by carrying out conversions. However the situation rapidly
  1363. becomes impossible with more than 4 or 5 types.
  1364.  
  1365. Doug Lea told me that it was possible to avoid this problem. I don't
  1366. know what his solution is. Here's mine.
  1367.  
  1368. Each matrix type includes routines for extracting individual rows or
  1369. columns. I assume a row or column consists of a sequence of zeros, a
  1370. sequence of stored values and then another sequence of zeros. Only a
  1371. single algorithm is then required for each binary operation. The rows
  1372. can be located very quickly since most of the matrices are stored row by
  1373. row. Columns must be copied and so the access is somewhat slower. As far
  1374. as possible my algorithms access the matrices by row.
  1375.  
  1376. An alternative approach of using iterators will be slower since the
  1377. iterators will involve a virtual function access at each step.
  1378.  
  1379. In fact, I provide several algorithms for operations like + . If one is
  1380. adding two matrices of the same type then there is no need to access the
  1381. individual rows or columns and a faster general algorithm is
  1382. appropriate.
  1383.  
  1384. Generally the method works well. However symmetric matrices are not
  1385. always handled very efficiently (yet) since complete rows are not stored
  1386. explicitly.
  1387.  
  1388. The original version of the package did not use this access by row or
  1389. column method and provided the multitude of algorithms for the
  1390. combination of different matrix types. The code file length turned out
  1391. to be just a little longer than the present one when providing the same
  1392. facilities with 5 distinct types of matrices. It would have been very
  1393. difficult to increase the number of matrix types in the original
  1394. version. Apparently 4 to 5 types is about the break even point for
  1395. switching to the approach adopted in the present package.
  1396.  
  1397.  
  1398. Using const
  1399. -----------
  1400.  
  1401. The memory management scheme introduces a problem when a matrix is
  1402. declared const. Because an operator may want to recycle the memory of
  1403. its operands these operands cannot be declared const. It isn't
  1404. reasonable for a temporary matrix to be declared const. However, I don't
  1405. know how to tell this to the C++ compiler. One possibility is to provide
  1406. alternative versions of the operators for operands declared const. But
  1407. then one gets the explosion in the number of operators.
  1408.  
  1409. My solution is to include versions of the initialisers for matrices
  1410. declared const. Otherwise, you need to use A.c() in place of A if A is
  1411. declared const and you wish to use it in an expression.
  1412.  
  1413.  
  1414. A calculus of matrix types
  1415. --------------------------
  1416.  
  1417. The program needs to be able to work out the class of the result of a
  1418. matrix expression. This is to check that a conversion is legal or to
  1419. determine the class of a temporary. To assist with this, a class
  1420. MatrixType is defined. Operators +, -, *, >= are defined to calculate
  1421. the types of the results of expressions or to check that conversions are
  1422. legal.
  1423.  
  1424.  
  1425. Error handling
  1426. --------------
  1427.  
  1428. The package does not have graceful exit from errors. All errors are
  1429. treated as fatal. Originally I thought I would wait until exceptions
  1430. became available in C++. This now seems to have been delayed. In any
  1431. case I don't think exceptions will solve all the problems. Some clean up
  1432. of objects on the heap will often be required before one can exit via an
  1433. exception.
  1434.  
  1435. There are four categories of errors:
  1436.  
  1437.    Programming error - eg illegal conversion of a matrix, subscript out
  1438.    of bounds, matrix dimensions don't match;
  1439.  
  1440.    Illegal data error - eg Cholesky of a non-positive definite matrix;
  1441.  
  1442.    Out of space error - "new" returns a null pointer;
  1443.  
  1444.    Convergence failure - an iterative operation fails to converge.
  1445.  
  1446. For the first two of these, it might be sensible to terminate a program.
  1447. For the second two, one does want to return control to the user's
  1448. program in a convenient manner. I don't know a good way of doing this,
  1449. especially before exceptions are implemented.
  1450.  
  1451.  
  1452. Band and sparse matrices
  1453. ------------------------
  1454.  
  1455. The package does not yet support band or sparse types. At present the
  1456. package assumes that the structure of a matrix is determined by its
  1457. class and dimensions. This is not sufficient for band and sparse
  1458. matrices.
  1459.  
  1460. For band matrices one also needs to know the upper and lower band
  1461. widths. For sparse matrices there is going to be some kind of structure
  1462. vector. These are going to have to be calculated for the results of
  1463. expressions in much the same way that types are calculated. In addition,
  1464. a whole new set of row and column operations would have to be written
  1465. for sparse matrices. However the present ones will be fine for band
  1466. matrices.
  1467.  
  1468. Band and sparse matrices are important for people solving large
  1469. sets of differential equations. Sparse matrices are also important for
  1470. statistical and operational research applications.
  1471.  
  1472.  
  1473. -------------------------------------------------------------------------------
  1474.  
  1475.  
  1476.                    Matrix package problem report form
  1477.                    ----------------------------------
  1478.  
  1479. Version: ...............newmat03
  1480. Date of release: .......Nov 28th, 1991
  1481. Primary site: ..........comp.sources.misc
  1482. Downloaded from: .......
  1483. Your email address: ....
  1484. Today's date: ..........
  1485. Your machine: ..........
  1486. Compiler & version: ....
  1487. Describe the problem - attach examples if possible:
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497. Email to  robert@am.dsir.govt.nz  or  Compuserve 72777,656 
  1498.  
  1499. -------------------------------------------------------------------------------
  1500.